package com.ihr360.oneclick.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.ihr360.commons.lang.DateUtils;
import com.ihr360.oneclick.constant.DtoFieldName;
import com.ihr360.oneclick.constant.SpreadsheetRowColumnMeta;
import com.ihr360.oneclick.dao.SpreadsheetTempRowDao;
import com.ihr360.oneclick.dto.spreadsheet.SpreadsheetDto;
import com.ihr360.oneclick.dto.spreadsheet.SpreadsheetTempRowDto;
import com.ihr360.oneclick.entity.RowHeaderColumn;
import com.ihr360.oneclick.entity.SpreadsheetRow;
import com.ihr360.oneclick.request.SearchRequest;
import com.ihr360.oneclick.request.query.SpreadSheetRowQueryParam;
import com.ihr360.oneclick.service.RowHeaderColumnService;
import com.ihr360.oneclick.service.SpreadsheetTempRowService;
import com.ihr360.oneclick.util.BeanConvertUtils;
import com.ihr360.oneclick.util.PageableUtils;
import com.ihr360.oneclick.vo.PageData;
import com.ihr360.oneclick.vo.SpreadsheetRowVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 电子表格数据处理业务层
 *
 * @author tom
 * @date 17-12-25
 */
@Service
public class SpreadsheetTempRowServiceImpl implements SpreadsheetTempRowService {

    @Autowired
    private SpreadsheetTempRowDao spreadSheetRowDao;
    @Autowired
    private RowHeaderColumnService rowHeaderColumnService;



    private Specification<SpreadsheetTempRowDto> buildSpecification(String companyId, String termId,
                                                                    String spreadsheetId,
                                                                    String staffRecordId,
                                                                    Map<String, RowHeaderColumn> fixedColumnMap,
                                                                    SpreadSheetRowQueryParam queryParam) {
        return (root, cq, cb) -> {
            Predicate predicate = cb.conjunction();
            List<Expression<Boolean>> expressionList = predicate.getExpressions();
            expressionList.add(cb.equal(root.get(DtoFieldName.SpreadsheetRow.COMPANY_ID), companyId));
            if(StringUtils.isNotBlank(termId)) {
                expressionList.add(cb.equal(root.get(DtoFieldName.SpreadsheetRow.TERM_ID), termId));
            }
            if(StringUtils.isNotBlank(spreadsheetId)) {
                expressionList.add(cb.equal(root.<SpreadsheetDto>get("spreadsheet").<String>get("id"), spreadsheetId));
            }
            if(StringUtils.isNotBlank(staffRecordId)) {
                expressionList.add(cb.equal(root.get(DtoFieldName.SpreadsheetRow.STAFF_RECORD_ID), staffRecordId));
            }
            if (queryParam != null) {
                if (queryParam.getGtOrEqStartMonth() != null) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.MONTH).getColumnFieldName();
                    expressionList.add(cb.greaterThanOrEqualTo(root.<String>get(columnFieldName),
                            DateUtils.formatDateStr(queryParam.getGtOrEqStartMonth(), DateUtils.STANDARD_DATE_FORMAT_YM1)));
                }
                if (queryParam.getLtOrEqEndMonth() != null) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.MONTH).getColumnFieldName();
                    expressionList.add(cb.lessThanOrEqualTo(root.<String>get(columnFieldName),
                            DateUtils.formatDateStr(queryParam.getLtOrEqEndMonth(), DateUtils.STANDARD_DATE_FORMAT_YM1)));
                }
                if (StringUtils.isNotBlank(queryParam.getEqMonthStr())) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.MONTH).getColumnFieldName();
                    expressionList.add(cb.equal(root.<String>get(columnFieldName), queryParam.getEqMonthStr()));
                }
                if (StringUtils.isNotBlank(queryParam.getEqStaffName())) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.STAFF_NAME).getColumnFieldName();
                    expressionList.add(cb.equal(root.get(columnFieldName), queryParam.getEqStaffName()));
                }
                if (StringUtils.isNotBlank(queryParam.getEqIdCardType())) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.IDCARD_TYPE).getColumnFieldName();
                    expressionList.add(cb.equal(root.get(columnFieldName), queryParam.getEqIdCardType()));
                }
                if (StringUtils.isNotBlank(queryParam.getEqIdCardNo())) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.IDCARD_NO).getColumnFieldName();
                    expressionList.add(cb.equal(root.get(columnFieldName), queryParam.getEqIdCardNo()));
                }
                if (StringUtils.isNotBlank(queryParam.getEqMobileNo())) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.MOBILE_NO).getColumnFieldName();
                    expressionList.add(cb.equal(root.get(columnFieldName), queryParam.getEqMobileNo()));
                }
                if (queryParam.getEqPublishStatus() != null) {
                    expressionList.add(cb.equal(root.<Boolean>get(DtoFieldName.SpreadsheetRow.PUBLISH_STATUS), queryParam.getEqPublishStatus()));
                }
                if (queryParam.getEqAllowPublish() != null) {
                    String columnFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.ALLOW_PUBLISH).getColumnFieldName();
                    expressionList.add(cb.equal(root.get(columnFieldName), queryParam.getEqAllowPublish()));
                }
                if(StringUtils.isNotBlank(queryParam.getLikeStaffNameOrIdCardNoOrMobileNo())) {
                    String mobileNOFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.MOBILE_NO).getColumnFieldName();
                    String idCardNoFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.IDCARD_NO).getColumnFieldName();
                    String staffNameFieldName = fixedColumnMap.get(SpreadsheetRowColumnMeta.STAFF_NAME).getColumnFieldName();
                    Predicate mobileNoPredicate = cb.like(root.get(mobileNOFieldName), "%" + queryParam.getLikeStaffNameOrIdCardNoOrMobileNo() + "%");
                    Predicate idCardNoPredicate = cb.like(root.get(idCardNoFieldName), "%" + queryParam.getLikeStaffNameOrIdCardNoOrMobileNo() + "%");
                    Predicate staffNamePredicate = cb.like(root.get(staffNameFieldName), "%" + queryParam.getLikeStaffNameOrIdCardNoOrMobileNo() + "%");
                    return cb.and(predicate, cb.or(mobileNoPredicate, idCardNoPredicate, staffNamePredicate));
                }
            }
            return predicate;
        };
    }

    @Override
    public PageData<SpreadsheetRowVo> getSpreadsheetRowPageData(String companyId, String spreadsheetId, SearchRequest<SpreadSheetRowQueryParam> searchRequest){
        Map<String, RowHeaderColumn> fixedColumnMap = rowHeaderColumnService.getSpreadsheetColumnMap(spreadsheetId);
        Specification<SpreadsheetTempRowDto> specification = buildSpecification(companyId, null, spreadsheetId, null, fixedColumnMap, searchRequest.getQueryParam());
        List<Sort.Order> sortFieldList = new ArrayList<>();
        sortFieldList.add(new Sort.Order(Sort.Direction.ASC, "createdAt"));
        sortFieldList.add(new Sort.Order(Sort.Direction.ASC, "rowIndex"));
        searchRequest.setOrderList(sortFieldList);
        searchRequest.setSortDirection(Sort.Direction.DESC);
        Page<SpreadsheetTempRowDto> page = spreadSheetRowDao.findAll(specification, PageableUtils.generatePageable(searchRequest));
        List<SpreadsheetRowVo> rowList = new ArrayList<>();
        RowHeaderColumn allowPublishColumn = fixedColumnMap.get(SpreadsheetRowColumnMeta.ALLOW_PUBLISH);
        page.getContent().forEach(spreadsheetRowDto -> {
            SpreadsheetRowVo spreadsheetRow = new SpreadsheetRowVo();
            spreadsheetRow.setId(spreadsheetRowDto.getId());
            spreadsheetRow.setStaffRecordId(spreadsheetRowDto.getStaffRecordId());
            List<Object> cellValueList = JSONArray.parseArray(spreadsheetRowDto.getDataStr(), Object.class);
            Boolean allowPublish = (Boolean) cellValueList.get(allowPublishColumn.getColumnIndex());
            cellValueList.set(allowPublishColumn.getColumnIndex(),
                    (allowPublish != null && allowPublish) ? "是" : "否");
            cellValueList.add(fixedColumnMap.size(),
                    (spreadsheetRowDto.getPublishStatus() != null && spreadsheetRowDto.getPublishStatus()) ? "已发布" : "未发布");
            spreadsheetRow.setCellValueList(cellValueList);
            rowList.add(spreadsheetRow);
        });
        PageData<SpreadsheetRowVo> pageData = new PageData<>(page);
        pageData.setContent(rowList);
        return pageData;
    }

    @Override
    public List<SpreadsheetRow> getSpreadsheetRowBySpreadsheetId(String spreadsheetId) {
        List<SpreadsheetTempRowDto> spreadsheetTempRowDtoList = spreadSheetRowDao.findBySpreadsheetId(spreadsheetId);
        List<SpreadsheetRow> spreadsheetRowList = new ArrayList<>();
        spreadsheetTempRowDtoList.forEach(spreadsheetTempRowDto ->
                spreadsheetRowList.add(BeanConvertUtils.convertFor(spreadsheetTempRowDto, new SpreadsheetRow()))
        );
        return spreadsheetRowList;
    }
}
